﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Threading;


namespace OTPlus.Core.Storage
{
    /// <summary>
    /// Represents a container of ActivityFetchCacheItems. Designed primarily for cache management.
    /// </summary>
    public class ActivityFetchCache : List<ActivityFetchCacheItem>
    {

        public ActivityFetchCache()
        {
  
        }

        /// <summary>
        /// Designed to be executed asynchronously with reckless abandon. Queues up appropriate threads to refresh data.
        /// </summary>
        /// <param name="access_token">Must be provided because we lose http context in the asynch calls.</param>
        public void RefreshIncremenetalCacheData(String access_token)
        {
            //600 members would take 10 minutes at one per second,
            //or 1 minute at 10 per second
            //not a perfect algorhythm. in fact it's terrible lol

            //Better: multiple algorhythm paying particular attention to users
            //with more recent activity.

            var queryList = (from afci in this.AccessCacheData()
                            orderby afci.LastChecked ascending
                                 select afci).Take(5);

            //foreach result in our little query, send them off to be worked on

            ActivityFetchCacheItemRequest request;

            foreach (var afci in queryList)
            {

                request = new ActivityFetchCacheItemRequest(afci, access_token);
                ThreadPool.QueueUserWorkItem(new WaitCallback(queryGoogle), request);
                //queryGoogle(request);
            }
        }

        private void queryGoogle(Object o)
        {
            ActivityFetchCacheItemRequest afcir = (ActivityFetchCacheItemRequest)o;

            //get that user's activities
            List<Content.Activity> activityList = Content.Activity.Retrieve(afcir.AccessToken, afcir.UserID);
            

            //add results to the threadsummarycache (used for forumdisplay)
            ThreadSummaryCache tsc = Core.Storage.ThreadSummaryCache.Instance.AccessCacheData();
            tsc.AddActivities(activityList);
            
            //update the afci and load it back into the cache
            afcir.LastChecked = DateTime.Now;
            afcir.RelevantRecordCount = activityList.Count; //TODO: determine what's "relevant" via linq query and put into here

            this.upsert(afcir);
        }

        private void upsert(ActivityFetchCacheItem afci)
        {
            //check to see if it exists in the cache first
            //bool exists = this.accessCacheData().Any(item => item.UserID == afci.UserID);
            //^ don't really care if it exists

            //remove it if it does
            this.AccessCacheData().RemoveAll(item => item.UserID == afci.UserID);
                    
            //add it back in
            this.AccessCacheData().Add(afci);
        }

        public ActivityFetchCache AccessCacheData()
        {

            ObjectCache cache = MemoryCache.Default;
            if (!cache.Contains("ActivityFetchData"))
            {
                CacheItemPolicy cip = new CacheItemPolicy();
                cip.Priority = CacheItemPriority.NotRemovable; //TODO: make sure this isn't stupid - ek
                cache.Add("ActivityFetchData", new ActivityFetchCache(), cip);
                this.loadEmptyData();
            }

            return (ActivityFetchCache)cache.Get("ActivityFetchData");
        }

        private void loadEmptyData()
        {
            //wherever we get the real data from. someone's circles, a spreadsheet, etc.

            this.AccessCacheData().Add(new ActivityFetchCacheItem("117572648855759587632", DateTime.Now.AddHours(-1), 0));
            this.AccessCacheData().Add(new ActivityFetchCacheItem("109378348199006115498", DateTime.Now.AddHours(-1), 0));
            this.AccessCacheData().Add(new ActivityFetchCacheItem("117456619770126101896", DateTime.Now.AddHours(-1), 0));
            this.AccessCacheData().Add(new ActivityFetchCacheItem("101888021664339151509", DateTime.Now.AddHours(-1), 0));
            this.AccessCacheData().Add(new ActivityFetchCacheItem("114890831955562032598", DateTime.Now.AddHours(-1), 0));
            this.AccessCacheData().Add(new ActivityFetchCacheItem("103551294686462547168", DateTime.Now.AddHours(-1), 0));
            this.AccessCacheData().Add(new ActivityFetchCacheItem("103913987674263347871", DateTime.Now.AddHours(-1), 0));
            this.AccessCacheData().Add(new ActivityFetchCacheItem("107466907386790104735", DateTime.Now.AddHours(-1), 0));            
        }

    }
}